"""AI Image Generation API endpoints for AncientSeeker.

Handles AI-powered image generation and management.
"""

from __future__ import annotations

from typing import List
from fastapi import APIRouter, Depends, HTTPException, Query
import logging
from sqlalchemy.orm import Session
from sqlalchemy import func
from pathlib import Path
import os

from app.database import get_db
from app.utils.auth import get_current_active_user
from app.models.user import User
from app.models.image_generation import ImageGeneration
from app.schemas.ai_request import ImageGenerateRequest
from app.schemas.ai_response import ImageGenerateResponse, ImageHistoryOut
from app.services.ai_service import image_ai_service
from app.config import settings


router = APIRouter()


@router.post("/generate-image", response_model=ImageGenerateResponse)
async def generate_image(
    image_request: ImageGenerateRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    """AI图像生成"""
    try:
        logger = logging.getLogger(__name__)
        # 调用AI图像生成服务
        # 允许前端传入 512x512 或 512*512，统一规范为 512*512 形式（与服务内部实现保持一致）
        normalized_size = (image_request.size or "1024*1024").lower().replace("x", "*")
        response = await image_ai_service.generate_image(
            prompt=image_request.prompt,
            style=image_request.style or "古典",
            size=normalized_size,
            user_id=current_user.id,
        )
        # 附加 user_subdir 便于前端调试（可选）
        response.setdefault("user_subdir", str(current_user.id))

        # 保存生成记录（容错：数据库未迁移时退化不保存 user_subdir 字段）
        try:
            image_record = ImageGeneration(
                user_id=current_user.id,
                prompt=image_request.prompt,
                style=image_request.style,
                image_url=response["image_url"],
                user_subdir=str(current_user.id),
                is_favorite=False,
            )
            db.add(image_record)
            db.commit()
            db.refresh(image_record)
        except Exception as db_err:
            db.rollback()
            msg = str(db_err).lower()
            if "no such column" in msg or "unknown column" in msg:
                logger.warning(
                    "image_generations.user_subdir 列不存在，回退为无隔离字段插入 (请执行数据库迁移)"
                )
                image_record = ImageGeneration(
                    user_id=current_user.id,
                    prompt=image_request.prompt,
                    style=image_request.style,
                    image_url=response["image_url"],
                    is_favorite=False,
                )
                db.add(image_record)
                db.commit()
            else:
                logger.error(f"写入图像记录失败: {db_err}")
                raise

        return ImageGenerateResponse(**response)
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"图像生成失败: {str(e)}")


@router.get("/images", response_model=List[ImageHistoryOut])
async def get_image_history(
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    favorites_only: bool = Query(False),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    """获取图像生成历史"""
    try:
        query = db.query(ImageGeneration).filter(
            ImageGeneration.user_id == current_user.id
        )

        if favorites_only:
            query = query.filter(ImageGeneration.is_favorite.is_(True))

        offset = (page - 1) * page_size
        images = (
            query.order_by(ImageGeneration.created_at.desc())
            .offset(offset)
            .limit(page_size)
            .all()
        )

        # 手动创建返回数据以避免model_validate问题
        result = []
        for image in images:
            result.append(
                {
                    "id": image.id,
                    "prompt": image.prompt,
                    "style": image.style,
                    "image_url": image.image_url,
                    "is_favorite": image.is_favorite,
                    "user_subdir": getattr(image, "user_subdir", None),
                    "created_at": image.created_at,
                }
            )

        return result

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取图像历史失败: {str(e)}")


@router.post("/images/{image_id}/favorite")
async def toggle_image_favorite(
    image_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    """切换图像收藏状态"""
    try:
        image_record = (
            db.query(ImageGeneration)
            .filter(
                ImageGeneration.id == image_id,
                ImageGeneration.user_id == current_user.id,
            )
            .first()
        )

        if not image_record:
            raise HTTPException(status_code=404, detail="图像记录不存在")

        current_flag = bool(getattr(image_record, "is_favorite", False))
        setattr(image_record, "is_favorite", not current_flag)
        db.commit()

        new_flag = bool(getattr(image_record, "is_favorite", False))
        action = "收藏" if new_flag else "取消收藏"
        return {"message": f"图像{action}成功", "is_favorite": new_flag}

    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=f"操作失败: {str(e)}")


@router.delete("/images/{image_id}")
async def delete_image(
    image_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    """删除图像生成记录并尝试物理移除对应文件。

    安全策略：
    - 仅当 image_url 以 /static 或 /static/generated 开头时尝试删除
    - 将 /static 前缀映射到后端真实 images 根目录 (app/data/images)
    - 删除失败不会影响数据库记录删除，记录失败日志
    """
    logger = logging.getLogger(__name__)
    try:
        image_record = (
            db.query(ImageGeneration)
            .filter(
                ImageGeneration.id == image_id,
                ImageGeneration.user_id == current_user.id,
            )
            .first()
        )
        if not image_record:
            raise HTTPException(status_code=404, detail="图像记录不存在")
        # 预先取出路径
        image_url = str(image_record.image_url or "")
        db.delete(image_record)
        db.commit()

        # 物理删除逻辑（尽最大努力）
        file_deleted = False
        physical_attempted = False
        try:
            if (
                settings.AI_IMAGE_PHYSICAL_DELETE
                and isinstance(image_url, str)
                and image_url.startswith("/static")
            ):
                physical_attempted = True

                # 统一解析相对部分
                rel_part = image_url[len("/static") :].lstrip("/")
                if rel_part.startswith("images/"):
                    rel_part = rel_part[len("images/") :]

                # 候选根目录（按优先级）：
                # 1. backend/data/images (实际保存位置)
                # 2. backend/app/data/images (旧/错误推断)
                # 3. 进程工作目录下 ./data/images 解析后的绝对路径
                candidates = [
                    Path(__file__).resolve().parents[2]
                    / "data"
                    / "images",  # backend/data/images
                    Path(__file__).resolve().parent.parent
                    / "data"
                    / "images",  # backend/app/data/images
                    Path("./data/images").resolve(),
                ]

                attempted_paths = []
                for base_dir in candidates:
                    target_path = base_dir / rel_part
                    attempted_paths.append(str(target_path))
                    try:
                        # 目录存在且文件存在
                        if target_path.exists() and target_path.is_file():
                            # 防止越界（理论上拼接后即在 base_dir 内，但仍做一次）
                            try:
                                target_path.relative_to(base_dir)
                            except ValueError:
                                logger.warning(
                                    f"[delete-image] 路径越界忽略: {target_path} base={base_dir}"
                                )
                                continue
                            target_path.unlink()
                            file_deleted = True
                            logger.info(
                                f"删除图像文件: {target_path} (base={base_dir}, rel={rel_part})"
                            )
                            break
                    except Exception as inner_fe:
                        logger.warning(
                            f"[delete-image] 尝试删除 {target_path} 时异常(忽略): {inner_fe}"
                        )

                logger.debug(
                    f"[delete-image] image_url={image_url} rel={rel_part} file_deleted={file_deleted} attempts={attempted_paths}"
                )
            else:
                logger.debug(
                    f"[delete-image] 物理删除未执行 flag={settings.AI_IMAGE_PHYSICAL_DELETE} url={image_url}"
                )
        except Exception as fe:
            logger.warning(f"物理删除图像文件失败 (忽略): {fe}")
        return {
            "message": "图像记录删除成功",
            "file_deleted": file_deleted,
            "physical_attempted": physical_attempted,
        }
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=f"删除图像记录失败: {str(e)}")


@router.get("/images/stats")
async def get_image_stats(
    db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)
):
    """获取用户图像生成统计"""
    try:
        total_images = (
            db.query(ImageGeneration)
            .filter(ImageGeneration.user_id == current_user.id)
            .count()
        )

        favorite_images = (
            db.query(ImageGeneration)
            .filter(
                ImageGeneration.user_id == current_user.id,
                ImageGeneration.is_favorite == True,
            )
            .count()
        )

        # 按风格统计
        style_stats = (
            db.query(
                ImageGeneration.style, func.count(ImageGeneration.id).label("count")
            )
            .filter(ImageGeneration.user_id == current_user.id)
            .group_by(ImageGeneration.style)
            .all()
        )

        return {
            "total_images": total_images,
            "favorite_images": favorite_images,
            "style_stats": [
                {"style": style, "count": count} for style, count in style_stats
            ],
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取统计数据失败: {str(e)}")
